package utils;

import com.sun.org.apache.xpath.internal.operations.String;
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Date;

/**
 * @program: Jef-orm
 * @description: 原子操作
 * @author: Cheng Zhi
 * @create: 2023-09-09 21:00
 **/
public class UnsafeUtils {

    static Unsafe UNSAFE = null;

    static {
        try {
            UNSAFE = reflectGetUnsafe();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 反射获取unsafe对象，引用Unsafe需使用如下反射方式，否则会抛出异常java.lang.SecurityException: Unsafe
     * @return
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    public static Unsafe reflectGetUnsafe() throws NoSuchFieldException, IllegalAccessException {
        Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        theUnsafe.setAccessible(true);//禁止访问权限检查（访问私有属性时需要加上）
        return (Unsafe) theUnsafe.get(null);
    }

    /**
     * 不使用反射直接创造对象，注意类的构造方法不会被执行
     * @param clz
     * @return 被构造的对象
     */
    @SuppressWarnings("unchecked")
    public final static <T> T newInstance(Class<T> clz){
        try {
            return (T) UNSAFE.allocateInstance(clz);
        } catch (InstantiationException e) {
            throw new IllegalStateException(e.getCause());
        }
    }

    /**
     * 获取一个字段的内存地址
     * @param field
     * @return
     */
    public static long getFiledSet(Field field) {
        return UNSAFE.objectFieldOffset(field);
    }

    /**
     * 给对象强制赋值
     * @param target  目标对象
     * @param offset  内存地址
     * @param value   值
     */
    public static void forcedSetValue(Object target, long offset, Object value) {

        if (value instanceof Integer) {
            UNSAFE.putInt(target, offset, (Integer) value);
        } else if (value instanceof Long) {
            UNSAFE.putLong(target, offset, (Long) value);
        } else if (value instanceof Float) {
            UNSAFE.putFloat(target, offset, (Float) value);
        } else if (value instanceof Boolean) {
            UNSAFE.putBoolean(target, offset, (Boolean) value);
        } else {
            UNSAFE.putObject(target, offset, value);
        }
    }

    /**
     * 强制获取字段值
     * @param field
     * @return
     */
    public static Object forcedGetValue(Object o, Field field) {

        long filedSet = getFiledSet(field);
        Type genericType = field.getGenericType();
        switch (genericType.getTypeName()) {
            case "java.lang.Integer":
                return UNSAFE.getObject(o, filedSet);
            case "int":
                return UNSAFE.getInt(o, filedSet);
            case "java.lang.Long":
                return UNSAFE.getObject(o, filedSet);
            case "long":
                return UNSAFE.getLong(o, filedSet);
            case "java.lang.Float":
                return UNSAFE.getObject(o, filedSet);
            case "float":
                return UNSAFE.getFloat(o, filedSet);
            case "java.lang.Double":
                return UNSAFE.getObject(o, filedSet);
            case "double":
                return UNSAFE.getObject(o, filedSet);
            case "java.lang.String":
                return UNSAFE.getObject(o,filedSet);
            case "java.util.Date":
                return UNSAFE.getObject(o, filedSet);
            default:
                throw new IllegalArgumentException("参数类型错误");
        }

    }
}
